package gang.org.springframework.framework.support;

import gang.org.springframework.framework.io.GangUrlResource;
import gang.org.springframework.framework.util.GangPropertiesLoaderUtils;
import gang.org.springframework.framework.util.GangStringUtils;

import java.io.IOException;
import java.net.URL;
import java.util.*;

/**
 * @author gang.chen
 * @description
 * @Date 2021/7/29 13:39
 */
public final class GangSpringFactoriesLoader {

    public static final String FACTORIES_RESOURCE_LOCATION="META-INF/spring.factories";

    public static List<String> loadFactoryNames(Class<?> factoryType, ClassLoader classLoader){
        //TODO
        ClassLoader classLoaderToUse = classLoader;

        String factoryTypeName = factoryType.getName();

        //TODO
        Map<String, List<String>> factoryImplementationMap = loadSpringFactories(classLoaderToUse);

        //TODO
        List<String> factoryImplementationList = factoryImplementationMap.getOrDefault(factoryTypeName, Collections.emptyList());

        return factoryImplementationList;
    }

    public static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader){
        //TODO
        Map<String, List<String>> result = new HashMap<>();

        try {
            Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
            while (urls.hasMoreElements()){
                URL url = urls.nextElement();
                GangUrlResource resource = new GangUrlResource(url);
                Properties properties = GangPropertiesLoaderUtils.loadProperties(resource);
                for (Map.Entry<Object, Object> entry : properties.entrySet()) {
                    String factoryTypeName = ((String) entry.getKey()).trim();
                    String[] factoryImplementationNames =
                            GangStringUtils.commaDelimitedListToStringArray((String)entry.getValue());

                    for (String factoryImplementationName : factoryImplementationNames) {
                        result.computeIfAbsent(factoryTypeName, key ->new ArrayList<>()).add(factoryImplementationName.trim());
                    }
                }
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }


}
